import { NavBar, InfiniteScroll, Toast, Popup } from 'antd-mobile'
import { useHistory, useParams } from 'react-router-dom'
import classNames from 'classnames'
import styles from './index.module.scss'
import DOMPurify from 'dompurify'
import Icon from '@/components/Icon'
import CommentItem from './components/CommentItem'
import CommentFooter from './components/CommentFooter'
import { useInitialState } from '@/utils/use-initial-state'
import {
  followAuthor,
  getArticle,
  collectArticle,
  likeArticle,
  getArticleComments,
  getArticleCommentsFirst,
  addArticleComment,
  articleCommentThumbUp,
} from '@/store/actions/article'
import { useEffect, useRef, useState } from 'react'
//滚动位置
import throttle from 'lodash/throttle'
//代码高亮
import highlight from 'highlight.js'
import 'highlight.js/styles/github.css'
//骨架屏
import ContentLoader from 'react-content-loader'
import { useDispatch } from 'react-redux'
import CommentInput from './components/CommentInput'
import { ArtComment } from '@/types/data'
import Reply from './components/Reply'
const NAV_BAR_HEIGTH = 45
enum CommentType {
  Article = 'a',
  Comment = 'c',
}
type CommentReply = {
  visible: boolean
  commentItem: ArtComment
}
const Article = () => {
  const history = useHistory()
  // 表示文章是否加载中的状态
  const dispatch = useDispatch()
  const [loading, setLoading] = useState(true)
  const [showReply, setShowReply] = useState<CommentReply>({
    visible: false,
    commentItem: {} as ArtComment,
  })
  const [commentVisible, setCommentVisible] = useState(false)
  const params = useParams<{ id: string }>()
  //评论回复
  const { detail, comments } = useInitialState(
    () => getArticle(params.id),
    'article',
    () => setLoading(false)
  )

  const wrapperRef = useRef<HTMLDivElement>(null)
  const authorRef = useRef<HTMLDivElement>(null)
  const [isShowNavAuthor, setIsShowNavAuthor] = useState(false)
  // 创建评论信息的DOM对象的 ref
  const commentRef = useRef<HTMLDivElement>(null)
  // 创建用来表示当前是否展示评论信息的ref
  const isShowComment = useRef(false)
  const onCommentShow = () => setCommentVisible(true)
  const onCommentHide = () => setCommentVisible(false)

  // 对于文章的评论数据来说，第一次获取需要自己手动发送请求
  useEffect(() => {
    dispatch(getArticleCommentsFirst(CommentType.Article, params.id, null))
  }, [dispatch, params.id])
  useEffect(() => {
    const wrapper = wrapperRef.current
    if (!wrapper) return
    const author = authorRef.current
    if (!author) return
    // 此处，通过节流函数 throttle 来降低滚动事件的触发频率
    const onScroll = throttle(() => {
      const { height, top } = author.getBoundingClientRect()
      if (top <= NAV_BAR_HEIGTH - height) {
        setIsShowNavAuthor(true)
      } else {
        setIsShowNavAuthor(false)
      }
    }, 100)
    wrapper.addEventListener('scroll', onScroll)
    return () => {
      wrapper.removeEventListener('scroll', onScroll)
    }
  }, [loading])
  // 点击跳转到评论内容
  const onShowComment = () => {
    const wrapper = wrapperRef.current
    if (!wrapper) return
    const comment = commentRef.current
    if (!comment) return

    const commentTop = comment.getBoundingClientRect().top
    if (!isShowComment.current) {
      wrapper.scrollTo({
        top: commentTop - NAV_BAR_HEIGTH + wrapper.scrollTop,
        behavior: 'auto',
      })
      isShowComment.current = true
    } else {
      wrapper.scrollTo(0, 0)
      isShowComment.current = false
    }
  }
  // 文章详情 代码内容 高亮
  useEffect(() => {
    const dgHtmlDOM = document.querySelector('.dg-html')
    const codes = dgHtmlDOM?.querySelectorAll<HTMLElement>('pre code')
    if (codes && codes.length > 0) {
      codes.forEach((el) => {
        highlight.highlightElement(el)
      })
      return
    }

    highlight.configure({
      // 忽略警告
      ignoreUnescapedHTML: true,
    })

    // 直接找到所有的 pre 标签
    const pres = dgHtmlDOM?.querySelectorAll('pre')
    if (pres && pres.length > 0) {
      pres.forEach((el) => {
        highlight.highlightElement(el)
      })
    }
  }, [detail])
  const {
    art_id,
    aut_id,
    attitude,
    is_collected,
    content,
    title,
    is_followed,
    pubdate,
    aut_name,
    aut_photo,
    comm_count,
    like_count,
    read_count,
  } = detail

  //骨架屏
  if (loading) {
    return (
      // 根据当前页面结构，设计好的 loading 效果
      <ContentLoader
        speed={2}
        width={375}
        height={230}
        viewBox="0 0 375 230"
        backgroundColor="#f3f3f3"
        foregroundColor="#ecebeb"
      >
        <rect x="16" y="8" rx="3" ry="3" width="340" height="10" />
        <rect x="16" y="26" rx="0" ry="0" width="70" height="6" />
        <rect x="96" y="26" rx="0" ry="0" width="50" height="6" />
        <rect x="156" y="26" rx="0" ry="0" width="50" height="6" />
        <circle cx="33" cy="69" r="17" />
        <rect x="60" y="65" rx="0" ry="0" width="45" height="6" />
        <rect x="304" y="65" rx="0" ry="0" width="52" height="6" />
        <rect x="16" y="114" rx="0" ry="0" width="340" height="15" />
        <rect x="263" y="208" rx="0" ry="0" width="94" height="19" />
        <rect x="16" y="141" rx="0" ry="0" width="340" height="15" />
        <rect x="16" y="166" rx="0" ry="0" width="340" height="15" />
      </ContentLoader>
    )
  }
  const onArticleCommentHide = () => setCommentVisible(false)
  // 发表评论
  const onAddComment = async (value: string) => {
    await dispatch(addArticleComment(art_id, value))

    onArticleCommentHide()
  }
  const renderCommentPopup = () => {
    return (
      <Popup
        className="comment-popup"
        position="bottom"
        visible={commentVisible}
        onMaskClick={onCommentHide}
      >
        <div className="comment-popup-wrapper">
          <CommentInput onClose={onCommentHide} onAddComment={onAddComment} />
        </div>
      </Popup>
    )
  }
  // 关注 或 取消关注作者
  const onFollowAuthor = async () => {
    await dispatch(followAuthor(aut_id, is_followed))
    Toast.show({
      content: is_followed ? '已取消关注' : '已关注',
      duration: 800,
    })
  }
  //收藏
  const onCollected = async () => {
    await dispatch(collectArticle(art_id, is_collected))
    Toast.show(is_collected ? '取消收藏' : '已收藏')
  }
  //点赞
  const onLike = async () => {
    await dispatch(likeArticle(art_id, attitude))
    Toast.show(attitude === 1 ? '取消点赞' : '已点赞')
  }
  // 创建枚举，来表示评论类型

  const { end_id, last_id, results } = comments
  const hasMore = end_id !== last_id

  // 对于文章的评论数据来说，第一次获取需要自己手动发送请求
  // 注意：为了避免脚手架热更新时，请求再次发送获取第一页数据重复，所以，该请求我们使用覆盖数据，而不是追加数据

  //拿数据
  const loadMoreComments = async () => {
    await dispatch(getArticleComments(CommentType.Article, params.id, last_id))
  }
  //对评论点赞
  const onThumbsUp = async (id: string, is_liking: boolean) => {
    await dispatch(articleCommentThumbUp(id, is_liking))
  }

  //关闭评论回复
  const onReplyHide = () => {
    setShowReply({ ...showReply, visible: false })
  }
  //渲染评论回复的弹出层
  const renderReply = () => {
    return (
      <Popup
        className="reply-popup"
        position="right"
        visible={showReply.visible}
      >
        <div className="comment-popup-wrapper">
          <Reply
            onClose={onReplyHide}
            commentItem={showReply.commentItem}
            // onReplyThumbUp={onThumbsUp}
            // articleId={params.id}
          />
        </div>
      </Popup>
    )
  }
  // 文章详情
  const renderArticle = () => {
    return (
      <div className="wrapper" ref={wrapperRef}>
        <div className="article-wrapper">
          <div className="header">
            <h1 className="title">{title}</h1>

            <div className="info">
              <span>{pubdate}</span>
              <span>{read_count} 阅读</span>
              <span>{comm_count} 评论</span>
            </div>

            <div className="author" ref={authorRef}>
              <img
                src={
                  aut_photo || 'http://geek.itheima.net/images/user_head.jpg'
                }
                alt=""
              />
              <span className="name">{aut_name}</span>
              <span
                onClick={onFollowAuthor}
                className={classNames('follow', is_followed ? 'followed' : '')}
              >
                {is_followed ? '已关注' : '关注'}
              </span>
            </div>
          </div>

          <div className="content">
            <div
              className="content-html dg-html"
              dangerouslySetInnerHTML={{
                __html: DOMPurify.sanitize(content),
              }}
            />
            <div className="date">发布文章时间：{pubdate}</div>
          </div>
        </div>

        <div className="comment" ref={commentRef}>
          <div className="comment-header">
            <span>全部评论（{comm_count}）</span>
            <span>{like_count} 点赞</span>
          </div>

          <div className="comment-list">
            {results.map((item) => {
              return (
                <CommentItem
                  key={item.com_id}
                  {...item}
                  onThumbsUp={() => onThumbsUp(item.com_id, item.is_liking)}
                  onReplyShow={() =>
                    setShowReply({ visible: true, commentItem: item })
                  }
                />
              )
            })}

            <InfiniteScroll hasMore={hasMore} loadMore={loadMoreComments} />
          </div>
        </div>
      </div>
    )
  }

  return (
    <div className={styles.root}>
      <div className="root-wrapper">
        <NavBar
          onBack={() => history.go(-1)}
          right={
            <span>
              <Icon type="icongengduo" />
            </span>
          }
        >
          {isShowNavAuthor && (
            <div className="nav-author">
              <img
                src={
                  aut_photo || 'http://geek.itheima.net/images/user_head.jpg'
                }
                alt=""
              />
              <span className="name">{aut_name}</span>
              <span
                className={classNames('follow', is_followed ? 'followed' : '')}
              >
                {is_followed ? '已关注' : '关注'}
              </span>
            </div>
          )}
        </NavBar>
        {/* 文章详情和评论 */}
        {renderArticle()}

        {/* 底部评论栏 */}
        <CommentFooter
          onShowComment={onShowComment}
          comm_count={comm_count}
          is_collected={is_collected}
          onCollected={onCollected}
          attitude={attitude}
          onLike={onLike}
          onCommentPopup={onCommentShow}
        />
      </div>
      {/* 创建文章评论的弹出层 */}
      {renderCommentPopup()}
      {/* 文章评论回复的弹出层 */}
      {renderReply()}
    </div>
  )
}

export default Article
